<?php
/**
 * Created by PhpStorm.
 * User: wiggin
 * Date: 2017/11/3
 */

namespace App\Utility\Db;

use Conf\Config;

class Redis
{
    private $con;
    protected static $instance;
    protected $tryConnectTimes = 0;
    protected $maxTryConnectTimes = 3;

    function __construct()
    {
        $this->connect();
    }

    function connect()
    {
        $this->tryConnectTimes++;
        $conf = Config::getInstance()->getConf("REDIS");
        $this->con = new \Redis();
        $this->con->connect($conf['HOST'], $conf['PORT'], 2);
        //$this->con->auth($conf['AUTH']);
        if (!$this->ping()) {
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->connect();
            } else {
                trigger_error("redis connect fail");
                return null;
            }
        }
        $this->con->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP);
    }

    static function getInstance()
    {
        if (is_object(self::$instance)) {
            return self::$instance;
        } else {
            self::$instance = new Redis();
            return self::$instance;
        }
    }

    function rPush($key, $val)
    {
        try {
            return $this->con->rpush($key, $val);
//            return $ret;
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->rPush($key, $val);
            } else {
                return false;
            }

        }

    }

    function lPop($key)
    {
        try {
            return $this->con->lPop($key);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->lPop($key);
            } else {
                return false;
            }

        }
    }

    function lSize($key)
    {
        try {
            $ret = $this->con->lSize($key);
            return $ret;
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->lSize($key);
            } else {
                return false;
            }

        }
    }

    function getRedisConnect()
    {
        return $this->con;
    }

    function ping()
    {
        try {
            $ret = $this->con->ping();
            if (!empty($ret)) {
                $this->tryConnectTimes = 0;
                return true;
            } else {
                return false;
            }
        } catch (\Exception $e) {
            return false;
        }
    }

    public function transaction()
    {
        try {
            return $this->con->multi();
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->transaction();
            } else {
                return false;
            }
        }
    }

    public function redisExec()
    {
        try {
            return $this->con->exec();
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->redisExec();
            } else {
                return false;
            }
        }
    }

    /*******************************************HASH MAP start *********************************************************/
    /**
     * @param $key
     * @param $field
     * @param $value
     * @return bool
     */
    public function hSet($key, $field, $value)
    {
        try {
            return $this->con->hSet($key, $field, $value);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hSet($key, $field, $value);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @param $field
     * @return bool
     */
    public function hGet($key, $field)
    {
        try {
            return $this->con->hGet($key, $field);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hGet($key, $field);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @param $field
     * @return bool
     */
    public function hExists($key, $field)
    {
        try {
            return $this->con->hExists($key, $field);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hExists($key, $field);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @return bool
     */
    public function hLen($key)
    {
        try {
            return $this->con->hLen($key);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hLen($key);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @param $field
     * @return bool
     */
    public function hDel($key, $field)
    {
        try {
            return $this->con->hdel($key, $field);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hDel($key, $field);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @return bool
     */
    public function hKeys($key)
    {
        try {
            return $this->con->hKeys($key);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hKeys($key);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @return bool
     */
    public function hVals($key)
    {
        try {
            return $this->con->hVals($key);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hVals($key);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @param $data
     * @return bool
     */
    public function hMSet($key, $data)
    {
        try {
            return $this->con->hMset($key, $data);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hMSet($key, $data);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @param $fields
     * @return bool
     */
    public function hMGet($key, $fields)
    {
        try {
            return $this->con->hMGet($key, $fields);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hMGet($key, $fields);
            } else {
                return false;
            }
        }
    }

    /**
     * @param $key
     * @return bool
     */
    public function hGetAll($key)
    {
        try {
            return $this->con->hGetAll($key);
        } catch (\Exception $e) {
            $this->connect();
            if ($this->tryConnectTimes <= $this->maxTryConnectTimes) {
                return $this->hGetAll($key);
            } else {
                return false;
            }
        }
    }

}

